import { Promise } from 'drunk-base';
import {observable} from "mobx";

export interface IItemProps {
    id?: string;
    version?: number;
    createdAt?: number;
    createdBy?: string;
    updatedAt?: number;
    updatedBy?: string;
}

type ValidateProp = {
    name: string;
    message: string;
};

export function Validate(message: string) {
    return (target: ItemModel<{}>, name: string, descriptor: PropertyDescriptor) => {
        let ctor: { validateProps: ValidateProp[] } = target.constructor as any;
        if (!ctor.validateProps) {
            ctor.validateProps = [];
        }
        ctor.validateProps.push({ name, message });
    };
}

export abstract class ItemModel<T extends IItemProps> {

    static validateProps: ValidateProp[];

    @observable isSubmiting: boolean;

    data: T;

    constructor(public id?: string) { }

    abstract fetchItemImpl(id: string): Promise<T>;

    abstract updateItemImpl(id: string, data: T): Promise<T>;

    abstract createItemImpl(data: T): Promise<T>;

    fetchData() {
        return this.fetchItemImpl(this.id).then(res => {
            this.data = res;
        });
    }

    save() {
        if (this.isSubmiting) {
            return Promise.reject({ success: false, message: `请在提交，请勿重复操作` });
        }

        let result = this.validateExcept();

        if (!result.success) {
            return Promise.reject(result);
        }

        let {
            id, version, createdAt, createdBy, updatedAt, updatedBy,
            ...data } = this.data as any;
        let promise: Promise<T>;

        if (this.id != null) {
            data["version"] = this.data.version;
            promise = this.updateItemImpl(this.data.id, data);
        }
        else {
            promise = this.createItemImpl(data);
        }

        this.isSubmiting = true;
        return promise.then(
            res => {
                this.isSubmiting = false;
                this.data = res;
                this.id = res.id;
                return { success: true, message: "提交成功", data: res }
            },
            e => {
                this.isSubmiting = false;
                return Promise.reject({ success: false, message: `提交失败，${e.res.message}` });
            }
        );
    }

    /**
     * dontValidateProps: 传进来的这几个字段不用验证
     */
    validateExcept(...dontValidateProps: string[]) {
        let validateProps = this.constructor['validateProps'];

        if (validateProps) {
            for (let i = 0, prop: ValidateProp; prop = validateProps[i]; i++) {
                if (dontValidateProps.indexOf(prop.name) < 0 && !this[prop.name]) {
                    return { success: false, message: prop.message };
                }
            }
        }

        return { success: true, message: "" };
    }
}